#pragma once

#include <unknwn.h>

namespace rt { namespace Fakes {

class FakeUnknown : public IUnknown
{
public:
	static FakeUnknown *GetInstance();

    /*** IUnknown methods ***/
    STDMETHOD(QueryInterface)(REFIID riid, void** ppvObj);
    STDMETHOD_(ULONG,AddRef)();
    STDMETHOD_(ULONG,Release)();

	bool QueryInterfaceCalled() const { return _queryInterfaceCalled; }
	IID const &QueryInterfaceLastRIID() const { return _queryInterfaceLastIID; }
	void QueryInterfaceFakeResult(void *result) { _queryInterfaceFakeResult = result; }
	void QueryInterfaceFakeError(HRESULT error) { _queryInterfaceFakeError = error; }

	bool AddRefCalled() const { return _addRefCalled; }
	void AddRefFakeResult(ULONG result) { _addRefFakeResult = result; }

	bool ReleaseCalled() const { return _releaseCalled; }
	void ReleaseFakeResult(ULONG result) { _releaseFakeResult = result; }

protected:
	FakeUnknown() : _queryInterfaceCalled(false),
		_queryInterfaceLastIID(IID_IUnknown),
		_queryInterfaceFakeResult(0),
		_queryInterfaceFakeError(S_OK),
		_addRefCalled(false),
		_addRefFakeResult(0),
		_releaseCalled(false),
		_releaseFakeResult(0)
	{}
	virtual ~FakeUnknown() {}

private:
	bool _queryInterfaceCalled;
	IID _queryInterfaceLastIID;
	void *_queryInterfaceFakeResult;
	HRESULT _queryInterfaceFakeError;

	bool _addRefCalled;
	ULONG _addRefFakeResult;

	bool _releaseCalled;
	ULONG _releaseFakeResult;
};

#define CONTAIN_UNKNOWN(member_) \
	STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj) { return member_.QueryInterface(iid, ppvObj); } \
	STDMETHOD_(ULONG, AddRef)() { return member_.AddRef(); } \
	STDMETHOD_(ULONG, Release)() { return member_.Release(); } \
	FakeUnknown member_

} }
